extern crate proc_macro;

use proc_macro::TokenStream;
use quote::quote;
use syn::{Field, ItemStruct, parse_macro_input, parse_quote};

/// 一个属性宏，用于向 SeaORM 实体结构体中添加通用字段：
/// - id: String (主键, UUIDv7)
/// - created_at: chrono::NaiveDateTime (创建时间)
/// - updated_at: chrono::NaiveDateTime (更新时间)
/// - deleted_at: Option<chrono::NaiveDateTime> (软删除时间戳)
pub fn add_sea_orm_common_fields(_attr: TokenStream, item: TokenStream) -> TokenStream {
    // 解析输入的 TokenStream 为一个结构体定义 (ItemStruct)
    let mut ast = parse_macro_input!(item as ItemStruct);

    // 准备要添加的字段定义
    // 注意：这些字段使用了 `parse_quote!` 来创建 `syn::Field` 类型。
    // 你需要确保你的项目中引入了 `chrono` crate 才能使用 `chrono::NaiveDateTime`。
    let id_field: Field = parse_quote! {
        #[sea_orm(primary_key, auto_increment = false, column_type = "Text", comment = "使用UUIDv7")]
        pub id: String
    };
    let created_at_field: Field = parse_quote! {
        #[sea_orm(column_type = "Timestamp", default_value = "CURRENT_TIMESTAMP")]
        pub created_at: chrono::NaiveDateTime
    };
    let updated_at_field: Field = parse_quote! {
        #[sea_orm(
            column_type = "Timestamp",
            default_value = "CURRENT_TIMESTAMP",
            on_update = "CURRENT_TIMESTAMP"
        )]
        pub updated_at: chrono::NaiveDateTime
    };
    let deleted_at_field: Field = parse_quote! {
        #[sea_orm(column_type = "Timestamp", nullable, comment = "软删除时间戳")]
        pub deleted_at: Option<chrono::NaiveDateTime>
    };

    match &mut ast.fields {
        syn::Fields::Named(f) => {
            // 重要提示：此宏期望用户不要在结构体中手动定义 id, created_at, updated_at, deleted_at 字段。
            // 如果用户定义了这些字段，当前逻辑将导致编译时字段重复定义的错误。
            // 这是为了确保这些公共字段完全由宏来管理。
            let existing_fields = f.named.clone();
            f.named.clear();

            f.named.push(id_field);

            for field in existing_fields.iter() {
                f.named.push(field.clone());
            }

            f.named.push(created_at_field);
            f.named.push(updated_at_field);
            f.named.push(deleted_at_field);
        }
        _ => {
            // 如果结构体不是命名字段结构体（例如单元结构体或元组结构体），则返回编译错误。
            return TokenStream::from(quote! {
                compile_error!("#[add_sea_orm_common_fields] 宏只能用于带命名字段的结构体。");
            });
        }
    }

    // 返回修改后的结构体定义的 TokenStream
    TokenStream::from(quote! {
        #ast
        impl sea_orm::ActiveModelBehavior for ActiveModel {
            fn before_save<'life0, 'async_trait, C>(
                mut self,
                _db: &'life0 C,
                insert: bool,
            ) -> ::core::pin::Pin<
                Box<
                    dyn ::core::future::Future<Output = Result<Self, DbErr>>
                        + ::core::marker::Send
                        + 'async_trait,
                >,
            >
            where
                C: ConnectionTrait,
                C: 'async_trait,
                'life0: 'async_trait,
                Self: ::core::marker::Send + 'async_trait,
            {
                Box::pin(async move {
                    if insert && self.id.is_not_set() {
                        self.id = sea_orm::ActiveValue::Set(uuid::Uuid::now_v7().into());
                    }
                    Ok(self)
                })
            }
        }
    })
}
